const sharp = require('sharp');
const logger = require('../utils/logger');

const fs = require('fs');
const path = require('path');

// 农历
const lunarCalendar = require('lunar-calendar');

// 获取今天日期
const todayString = new Date().toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric' }).replace(/\s/g, '');

// 今天是周几
const weekString = new Date().toLocaleDateString('zh-CN', { weekday: 'long' });

// 二维码地址
const defaultQrCodePath = path.resolve(__dirname, '..', 'assets', 'qrcode.jpg');
console.log("defaultQrCodePath", defaultQrCodePath);



// 画布尺寸
const CANVAS = {
    WIDTH: 1080,
    HEIGHT: 1920
};

// 二维码尺寸
const QR_CODE = {
    WIDTH: 200,
    HEIGHT: 200
};

// 颜色配置
const COLORS = {
    // 整体背景
    BACKGROUND: { r: 245, g: 245, b: 245, alpha: 1 },
    // 主色调
    PRIMARY: '#2962FF',
    // 白色
    WHITE: '#ffffff',
    // 深灰色
    GRAY_DARK: '#333333',
    // 中灰色
    GRAY_MEDIUM: '#666666',
    // 浅灰色
    GRAY_LIGHT: '#EEEEEE'
};

// 字体配置
const FONTS = {
    YAHEI: 'Microsoft YaHei'
};


/**
 * 处理文件上传的通用函数
 * @param {string} fileName - 文件名
 * @param {Buffer} fileBuffer - 文件内容
 * @returns {Promise<Object>} - 上传结果
 */
async function handleFileUpload(fileName, fileBuffer) {
    try {
        // 确保 fileName 是字符串
        if (typeof fileName !== 'string') {
            fileName = 'default.未知格式'; // 设置默认文件名
        }

        // 上传文件
        const uploadFileRes = await uniCloud.uploadFile({
            cloudPath: fileName,
            fileContent: fileBuffer
        });
        console.log('uploadFileRes : ', uploadFileRes);

        if (!uploadFileRes.fileID) {
            return {
                code: 500,
                msg: '文件上传失败，未返回fileID'
            };
        }

        // 获取临时文件URL
        const getTempFileURLRes = await uniCloud.getTempFileURL({
            fileList: [uploadFileRes.fileID],
        });
        console.log('getTempFileURLRes : ', getTempFileURLRes);

        if (!getTempFileURLRes.fileList[0]?.tempFileURL) {
            return {
                code: 500,
                msg: '获取临时文件URL失败'
            };
        }

        const tempFileURL = getTempFileURLRes.fileList[0].tempFileURL;
        return {
            code: 200,
            msg: '上传成功',
            data: {
                tempFileURL
            },
        };
    } catch (error) {
        console.error('文件上传失败:', error);
        return {
            code: 500,
            msg: '文件上传失败',
            error: error.message
        };
    }
}



// 获取今天的日期,年月日格式
function getTodayDate() {
    try {
        return new Date().toLocaleDateString('zh-CN', {
            year: 'numeric',
            month: 'numeric',
            day: 'numeric'
        }).replace(/(\d+)\/(\d+)\/(\d+)/, '$1年$2月$3日');
    } catch (error) {
        console.error('获取日期失败:', error.message);
        return '获取日期失败';
    }
}
// 获取今天是周几
function getWeekDay(date) {
    try {
        const dateObj = date ? new Date(date) : new Date();
        const week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
        return week[dateObj.getDay()];
    } catch (error) {
        console.error('获取星期失败:', error.message);
        return '获取星期失败';
    }
}

/**
 * 获取当前是一年中的第几周
 * @param {Date} date 日期对象
 * @returns {number} 周数
 */
function getWeekNumber(date = new Date()) {
    // 获取当年1月1日
    const firstDayOfYear = new Date(date.getFullYear(), 0, 1);

    // 计算当前日期与1月1日之间的毫秒数差
    const timeDiff = date - firstDayOfYear;

    // 将毫秒数转换为天数
    const dayDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24));

    // 计算周数（从0开始计数）
    const weekNumber = Math.floor(dayDiff / 7);

    // 如果1月1日不是周日，则第一周可能不足7天
    const firstDayWeekday = firstDayOfYear.getDay();
    if (firstDayWeekday !== 0 && weekNumber === 0) {
        return 1;
    }

    return weekNumber + 1;
}

// 获取今天的农历
function getLunarCalendar() {
    try {
        // 获取当前日期
        const today = new Date();
        const year = today.getFullYear();
        const month = today.getMonth() + 1;
        const day = today.getDate();

        // 调用农历转换函数
        const lunar = lunarCalendar.solarToLunar(year, month, day);
        // console.log('农历:', lunar);
        // 返回农历文本
        const lunarText = `${lunar.zodiac}年${lunar.lunarMonthName}${lunar.lunarDayName}`;
        // 返回农历日期对象
        return lunarText;
    } catch (error) {
        console.error('获取农历日期失败:', error.message);
        return null;
    }
}

// 生成SVG模板
function generateSvgTemplate(data) {
    const { date, issueNumber, newsItems, quote, qrCodePath } = data;
    // 年份
    const year = String(date.split('年')[0]).padStart(4, '0');
    // 月份
    const month = String(date.split('年')[1].split('月')[0]).padStart(2, '0');
    // 日期
    const day = String(date.split('月')[1].split('日')[0]).padStart(2, '0');

    // 周几
    const weekDay = getWeekDay();
    // 生成顶部区域
    function generateHeader() {
        return `
            <!-- 背景卡片 -->
            <path d="M0,0 L${CANVAS.WIDTH},0 L${CANVAS.WIDTH - 40},240 L0,240 Z" fill="${COLORS.PRIMARY}"/>
            <path d="M0,20 L${CANVAS.WIDTH - 20},20 L${CANVAS.WIDTH - 40},260 L0,260 Z" fill="${COLORS.PRIMARY}" opacity="0.3"/>
            <!-- 标题文本 -->
            <text x="60" y="160" font-family="${FONTS.YAHEI}" font-size="120" font-weight="bold" fill="${COLORS.WHITE}">今日简报</text>
            
            <!-- 日期和期数区域 -->
            <rect x="${CANVAS.WIDTH * 0.6}" y="80" width="380" height="120"  font-weight="bold" 
                  transform="skewX(-10)" fill="${COLORS.WHITE}" fill-opacity="0.2"/>
            
            <!-- 期数 -->
            <text x="${CANVAS.WIDTH * 0.6 + 30}" y="130" font-family="${FONTS.YAHEI}"  font-weight="bold"
                  font-size="36" fill="${COLORS.WHITE}">${year} | 第 ${issueNumber} 周</text>
            <!-- 日期 -->
            <text x="${CANVAS.WIDTH * 0.65}" y="185" font-family="${FONTS.YAHEI}"  font-weight="bold"
                  font-size="40" fill="${COLORS.WHITE}">${month}.${day}</text>
            <!-- 周几 -->
            <text x="${CANVAS.WIDTH * 0.7 + 80}" y="185" font-family="${FONTS.YAHEI}"  font-weight="bold"
                  font-size="40" fill="${COLORS.WHITE}">${weekDay}</text>
        `;
    }
    // 生成新闻列表区域
    function generateNewsList() {
        function generateNewsItem(newsItem, index) {
            const y = 380 + index * 90;
            // 新闻内容截断
            // 根据序号动态截断,最多34字,最少26字
            const index15 = index % 15;
            const maxLength = 27 - index15 * 0.2;
            const minLength = 22;
            const news = newsItem;
            const finalLength = Math.max(minLength, Math.min(maxLength, news.length));
            const truncatedNews = news.length > finalLength ? news.substring(0, finalLength) + '...' : news;
            // 序号格式化
            const formattedIndex = String(index + 1).padStart(2, '0');

            return `
                <!-- 新闻卡片背景 -->
                <rect x="40" y="${y - 50}" width="${CANVAS.WIDTH - 50}" height="70" 
                      transform="skewX(-5)" fill="${COLORS.GRAY_LIGHT}" opacity="0.5"/>
                
                <!-- 序号标记 -->
                <path d="M60,${y - 50} L100,${y - 50} L95,${y + 20} L55,${y + 20} Z" 
                      fill="${COLORS.PRIMARY}"/>
                <text x="62" y="${y - 2}" font-family="${FONTS.YAHEI}" 
                      font-size="24" font-weight="bold" fill="${COLORS.WHITE}">${formattedIndex}</text>
                
                <!-- 新闻内容 -->
                <text x="130" y="${y}" font-family="${FONTS.YAHEI}" 
                      font-size="32" fill="${COLORS.GRAY_DARK}">${truncatedNews}</text>
            `;
        }

        return `
            <!-- 新闻列表 -->
            ${newsItems.map((news, index) => generateNewsItem(news, index)).join('')}
        `;
    }

    // 生成底部区域
    function generateFooter() {
        return `
            <!-- 底部装饰 -->
            <path d="M30,${CANVAS.HEIGHT - 250} L${CANVAS.WIDTH - 30},${CANVAS.HEIGHT - 250} 
                     L${CANVAS.WIDTH - 60},${CANVAS.HEIGHT - 230} L60,${CANVAS.HEIGHT - 230} Z" 
                  fill="${COLORS.PRIMARY}" opacity="0.8"/>
                  
            <!-- 引用文本背景 -->
            <rect x="40" y="${CANVAS.HEIGHT - 200}" width="${CANVAS.WIDTH - 80}" height="180"
                  rx="20" ry="20" fill="${COLORS.PRIMARY}" opacity="0.05"/>

            <!-- 引用文本 -->
            <text x="80" y="${CANVAS.HEIGHT - 120}" font-family="${FONTS.YAHEI}" font-weight="bold" 
                  font-size="36" fill="${COLORS.PRIMARY}" letter-spacing="2">${quote}</text>
            
            <!-- 关注提示区域 -->
            <g transform="translate(180,${CANVAS.HEIGHT - 80})">
                <rect width="500" height="60" rx="30" fill="url(#gradient)"/>
                <defs>
                    <linearGradient id="gradient">
                        <stop offset="0%" style="stop-color:${COLORS.PRIMARY}"/>
                        <stop offset="100%" style="stop-color:#1565C0"/>
                    </linearGradient>
                </defs>
                
                <circle cx="40" cy="30" r="20" fill="${COLORS.WHITE}"/>
                <path d="M32,30 h16 M40,22 v16" stroke="${COLORS.PRIMARY}" 
                      stroke-width="4" stroke-linecap="round"/>
                
                <text x="90" y="40" font-family="${FONTS.YAHEI}" font-size="30"
                      fill="${COLORS.WHITE}" font-weight="bold">关注我们，60 秒速览天下事</text>
            </g>
        `;
    }

    // 合并所有区域
    return `
        <svg width="${CANVAS.WIDTH}" height="${CANVAS.HEIGHT}">
            <rect x="0" y="0" width="${CANVAS.WIDTH}" height="${CANVAS.HEIGHT}" fill="${COLORS.WHITE}"/>
            ${generateHeader()}
            ${generateNewsList()}
            ${generateFooter()}
        </svg>
    `;
}

/**
 * 生成海报
 * @param {Object} data - 海报数据
 * @param {string} data.date - 日期
 * @param {number} data.issueNumber - 期数
 * @param {Array<object>} data.newsItems - 新闻列表
 * @param {string} data.quote - 引用文本
 * @param {string} data.qrCodePath - 二维码图片路径
 * @returns {Promise<Buffer>} - 海报图片
 */
async function generatePoster(data) {
    // 参数校验
    if (!data) {
        throw new Error('缺少必要参数');
    }

    if (data.newsItems.length === 0) {
        throw new Error('新闻列表不能为空');
    }


    // 创建背景
    const background = await sharp({
        create: {
            width: CANVAS.WIDTH,
            height: CANVAS.HEIGHT,
            channels: 4,
            background: { r: 255, g: 255, b: 255, alpha: 1 }
        }
    });

    // 生成SVG内容
    const svg = generateSvgTemplate(data);

    try {
        // 处理二维码图片
        let qrCodeBuffer;
        if (data.qrCodePath.startsWith('http')) {
            // 如果是网络图片，使用 axios 下载
            const axios = require('axios');
            const response = await axios.get(data.qrCodePath, { responseType: 'arraybuffer' });
            qrCodeBuffer = Buffer.from(response.data, 'binary');
        } else {
            // 如果是本地图片，使用 fs 读取
            qrCodeBuffer = fs.readFileSync(data.qrCodePath);
        }

        // 合并背景、SVG文本和二维码
        const final = await background
            .composite([
                {
                    input: Buffer.from(svg),
                    top: 0,
                    left: 0
                },
                {
                    input: await sharp(qrCodeBuffer)
                        .resize(QR_CODE.WIDTH, QR_CODE.HEIGHT)
                        .toBuffer(),
                    top: CANVAS.HEIGHT - QR_CODE.HEIGHT - 10,
                    left: CANVAS.WIDTH - QR_CODE.WIDTH - 40
                }
            ])
            .png()
            .toBuffer();

        return final;
    } catch (error) {
        console.error(`生成海报失败: ${error.message}`);
        throw new Error(`生成海报失败: ${error.message}`);
    }
}



/**
 * 生成海报主函数
 * @param {Object} options 配置选项
 * @param {string[]} options.newsItems 新闻列表
 * @param {string} options.quote 引用文本
 * @param {string} options.qrCodePath 二维码路径
 * @param {string} options.tips 关注提示
 * @param {string} options.date 日期
 * @param {string} options.weekDay 周几
 * @param {string} options.lunar 农历
 * @param {number} options.issueNumber 期数
 * @returns {Promise<{posterBuffer: Buffer, posterData: Object, imageBase64: string}>} 生成的海报数据
 * @throws {Error} - 当缺少必要参数时抛出错误
 * 
 * @example
 * const result = await generateNewsPoster({
 *   newsItems: ['新闻1', '新闻2', '新闻3'],
 *   quote: '与其用十分钟抱怨，不如用一分钟解决问题。',
 *   qrCodePath: 'https://example.com/qrcode.jpg'
 * });
 */
async function generateNewsPoster(data) {
    logger.debug('开始生成海报，输入参数:', data);

    // 参数校验
    if (!data?.newsItems) {
        const error = new Error('缺少必要参数: newsItems');
        logger.error('参数校验失败:', error);
        throw error;
    }

    try {
        // 默认值处理
        const posterData = {
            date: data.date || getTodayDate(),
            weekDay: data.weekDay || getWeekDay(),
            lunar: data.lunar || getLunarCalendar(),
            issueNumber: data.issueNumber || getWeekNumber(),
            newsItems: data.newsItems,
            quote: data.quote || '与其用十分钟抱怨，不如用一分钟解决问题。',
            qrCodePath: data.qrCodePath || defaultQrCodePath,
            tips: data.tips || '关注我，每天 60 秒速览天下新鲜事。'
        };

        logger.debug('处理后的海报数据:', posterData);

        // 生成海报
        const posterBuffer = await generatePoster(posterData);
        logger.debug('海报生成成功，返回结果');

        const saveFileName = `${posterData.date}_${posterData.weekDay}资讯海报图.png`;

        const APIURL = 'https://env-00jxgx7alqyz.dev-hz.cloudbasefunction.cn/upload_file'
        const formData = new FormData();

        formData.append('file', new Blob([posterBuffer]), saveFileName);

        const response = await fetch(APIURL, {
            method: 'POST',
            body: formData
        });

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        const result = await response.json();
        console.log('将文件上传到 unicloud 成功:', result);

        if (result.code !== 200) {
            throw new Error(`海报上传失败: ${result.msg}`);
        }

        return {
            code: 200,
            message: '海报生成成功',
            data: result.data.tempFileURL,
            // posterBuffer,
            posterData,
        };
    } catch (error) {
        logger.error('❌ 海报生成失败:', error);
        throw error;
    }
}


module.exports = {
    generateNewsPoster
}


if (require.main === module) {

    // console.log(getLunarCalendar());
    generateNewsPoster({
        newsItems: ['新闻1', '新闻2', '新闻3']
    }).then(res => {
        console.log(res);
        require('fs').writeFileSync('./poster.png', res.posterBuffer);
    }).catch(err => {
        console.log(err);
    })

}